﻿/*********************************************************************************
**                                                                              **
**  Copyright (C) 2024 LiLong                                                   **
**  This file is part of GnssLogs.                                              **
**                                                                              **
**  GnssLogs is free software: you can redistribute it and/or modify            **
**  it under the terms of the GNU Lesser General Public License as published by **
**  the Free Software Foundation, either version 3 of the License, or           **
**  (at your option) any later version.                                         **
**                                                                              **
**  GnssLogs is distributed in the hope that it will be useful,                 **
**  but WITHOUT ANY WARRANTY; without even the implied warranty of              **
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               **
**  GNU Lesser General Public License for more details.                         **
**                                                                              **
**  You should have received a copy of the GNU Lesser General Public License    **
**  along with GnssLogs.  If not, see <https://www.gnu.org/licenses/>.          **
**********************************************************************************/
#pragma once

#include "../SATXYZ2.h"
#include "LogHeaderDecoder.h"

namespace GnssLogs
{
namespace SATXYZ2Decoder
{
using namespace tao::pegtl;
using Sync   = TAO_PEGTL_STRING("#SATXYZ2A");
using Header = LogHeaderDecoder::SyncExpression<Sync>;
// clang-format off
struct Sats : star<digit> {};

struct System : ascii::identifier {};
struct SatelliteID : star<digit> {};
struct X : Floating {};
struct Y : Floating {};
struct Z : Floating {};
struct ClkCorr : Floating {};
struct IonoDelay : Floating {};
struct TropoDelay : Floating {};
struct Reserved1 : Floating {};
struct Reserved2 : Floating {};
// clang-format on
using SatelliteRule = seq<Split,
                          System,
                          Split,
                          SatelliteID,
                          Split,
                          X,
                          Split,
                          Y,
                          Split,
                          Z,
                          Split,
                          ClkCorr,
                          Split,
                          IonoDelay,
                          Split,
                          TropoDelay,
                          Split,
                          Reserved1,
                          Split,
                          Reserved2>;

using Expression = seq<Header, Sats, star<SatelliteRule>, one<'*'>, CRC32, Tail>;

template<typename T>
struct Action
{
};

template<>
struct Action<Header> : LogHeaderDecoder::LogHeaderHelperNoSetValue
{
};

template<>
struct Action<Sats> : IntHelper<Action<Sats>, uint32_t>
{
    static void setValue(SATXYZ2::Data& data, uint32_t value) { data.satCount = value; }
};

template<>
struct Action<System> : EnumHelper<Action<System>, SatelliteSystem>
{
    static void setValue(SATXYZ2::Data& data, SatelliteSystem value)
    {
        data.sats.emplace_back(SATXYZ2::Data::Satellite {});
        data.sats.back().system = value;
    }
};

template<>
struct Action<SatelliteID> : IntHelper<Action<SatelliteID>, uint32_t>
{
    static void setValue(SATXYZ2::Data& data, uint32_t value) { data.sats.back().satelliteID = value; }
};

template<>
struct Action<X> : DoubleHelper<Action<X>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().x = value; }
};

template<>
struct Action<Y> : DoubleHelper<Action<Y>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().y = value; }
};

template<>
struct Action<Z> : DoubleHelper<Action<Z>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().z = value; }
};

template<>
struct Action<ClkCorr> : DoubleHelper<Action<ClkCorr>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().clkCorr = value; }
};

template<>
struct Action<IonoDelay> : DoubleHelper<Action<IonoDelay>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().ionoDelay = value; }
};

template<>
struct Action<TropoDelay> : DoubleHelper<Action<TropoDelay>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().tropoDelay = value; }
};

template<>
struct Action<Reserved1> : DoubleHelper<Action<Reserved1>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().reserved1 = value; }
};

template<>
struct Action<Reserved2> : DoubleHelper<Action<Reserved2>>
{
    static void setValue(SATXYZ2::Data& data, double value) { data.sats.back().reserved2 = value; }
};

template<>
struct Action<CRC32> : CRC32Helper<Action<CRC32>>
{
    static void setValue(SATXYZ2::Data& data, uint32_t value) { data.crc32 = value; }
};
} // namespace SATXYZ2Decoder
} // namespace GnssLogs